gusucode.com > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序 > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序/code/Src/Client/scwinlib/SCBitmap.cpp
//Download by http://www.NewXing.com /* * This file is part of the EMFexplorer projet. * Copyright (C) 2004 Smith Charles. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * Extension: for commercial use, apply the Equity Public License, which * adds to the normal terms of the GLPL a condition of donation to the author. * If you are interested in support for this source code, * contact Smith Charles <smith.charles@free.fr> for more information. */ #include "stdafx.h" #include "SCBitmap.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Create a n-bit-per-pixel surface. HBITMAP SCCreateDIBSection(HDC hDC, int iWidth, int iHeight, int iBitCount) { BITMAPINFO bmi; HBITMAP hbm; LPVOID pBits; // Initialize to 0s. ZeroMemory(&bmi, sizeof(bmi)); // Initialize the header. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = iWidth; bmi.bmiHeader.biHeight = iHeight; //warning: bottom-up bitmap bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = iBitCount; bmi.bmiHeader.biCompression = BI_RGB; // Create the surface. if (hDC) hbm = ::CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0); else {// use the screen HDC hSrcndc = ::GetDC(NULL); hbm = ::CreateDIBSection(hSrcndc, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0); ::ReleaseDC(NULL, hSrcndc); } return(hbm); } // Create a grayscale surface. HBITMAP SCCreateGrayScaleDIBSection(HDC hDC, int iWidth, int iHeight, int nBits/* = 8*/) { BITMAPINFO* pbmi=NULL; HBITMAP hbm; LPVOID pBits; HDC hRefDC; DWORD dwSize = sizeof(BITMAPINFO); UINT uEntries; switch (nBits) { case 2: uEntries = 4; break; case 4: uEntries = 16; break; case 8: uEntries = 256; break; default: return NULL; } hRefDC = GetDC( NULL ); if(hRefDC) { //SetStretchBltMode(hRefDC, HALFTONE); } else return NULL; // Create the logical palette based on the entries // Allocate memory for the palette. dwSize += uEntries*sizeof(PALETTEENTRY); pbmi = (BITMAPINFO*) new BYTE[dwSize]; if (!pbmi) { ReleaseDC( NULL, hRefDC ); return NULL; } // Initialize to 0s. ZeroMemory(pbmi, dwSize); LPPALETTEENTRY pPal = (LPPALETTEENTRY)&pbmi->bmiColors; // gray scale palette for (int i=0;(UINT)i<uEntries;i++) { pPal->peRed = pPal->peGreen = pPal->peBlue = (BYTE)(i & 0xFF); pPal->peFlags = 0; pPal++; } // Finish Initialize header. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = iWidth; pbmi->bmiHeader.biHeight = iHeight; //warning: bottom-up bitmap pbmi->bmiHeader.biPlanes = 1; pbmi->bmiHeader.biBitCount = nBits; pbmi->bmiHeader.biCompression = BI_RGB; //pbmi->bmiHeader.biClrUsed = uEntries; // Create the surface. if (hDC) hbm = ::CreateDIBSection(hDC, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0); else // use the screen hbm = ::CreateDIBSection(hRefDC, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0); delete [] pbmi; ReleaseDC( NULL, hRefDC ); return(hbm); } //Just extract the non-white block //The transparent color is white BYTE *SCExtractMemBoundingBox(BYTE *lpmem, LPRECT pR, DWORD dwSize, long sScanBytes, short sBitPel) { BYTE *lpTop = lpmem; BYTE *lpBottom = lpTop + dwSize; BYTE *lpTmp; ASSERT(lpmem && pR && dwSize && sScanBytes && sBitPel); if ( (!lpmem) || (!pR)|| (!dwSize) || (!sScanBytes) || (!sBitPel)) return NULL; long widthBytes = ((pR->right - pR->left)*(0L+sBitPel))/8; ASSERT(widthBytes<=sScanBytes); // top band lpTmp = lpTop; long top; while ((lpTop<lpBottom) && (0xFF == *lpTop)) { lpTop++; if (lpTop - lpTmp>=widthBytes) {// skip extra bytes lpTmp += sScanBytes; lpTop = lpTmp; } } // check full blank page if (lpTop>=lpBottom) { // blank page ::SetRectEmpty(pR); return lpBottom; } top = (long)((lpTop - lpmem) / sScanBytes); // line where drawing begins lpTop = lpmem + (top+0L) * sScanBytes; // adjust to first byte on scan line // bottom band lpTmp = lpBottom - sScanBytes; BYTE *lpRight = lpTmp + widthBytes; BOOL bOkB = FALSE; long bottom; while (lpTmp>lpTop) { lpBottom = lpTmp; // check this scan line, up to extra bytes while (lpBottom<lpRight) { if (0xFF != *lpBottom) { bOkB = TRUE; break; } lpBottom++; } if (bOkB) break; // go up one scan line lpTmp -= sScanBytes; lpRight -= sScanBytes; } bottom = (long)((lpBottom - lpmem) / sScanBytes); // after line where drawing ends lpBottom = lpmem + (bottom+0L) * sScanBytes; // adjust to first byte on next scan line // left band (scan one column at a time) BOOL bOkL = FALSE; long left=-1; while(left<widthBytes) { lpTmp = lpTop + (++left); while (lpTmp<lpBottom) { if(0xFF != *lpTmp) { bOkL = TRUE; pR->left=(int)((LONG)left*8) / sBitPel; break; } lpTmp += sScanBytes; } if (bOkL) break; } // right band BOOL bOkR = FALSE; long right=widthBytes; while (right>left) { lpTmp = lpTop + (--right); while (lpTmp<lpBottom) { if(0xFF != *lpTmp) { bOkR = TRUE; pR->right=(int)((LONG)right*8L) / sBitPel; break; } lpTmp += sScanBytes; } if (bOkR) break; } // transform left and right in pixels pR->top=top; pR->bottom=bottom; return lpBottom; } /// /// Make a copy of a GDI logical palette /// HPALETTE SCCopyPalette (HPALETTE hpal) { ASSERT(hpal); WORD nNumEntries; if (!hpal || !GetObject(hpal, sizeof(nNumEntries), &nNumEntries)) return NULL; if (nNumEntries == 0) return NULL; PLOGPALETTE pPal = (PLOGPALETTE) new BYTE[sizeof(LOGPALETTE) + nNumEntries * sizeof(PALETTEENTRY)]; if (!pPal) return NULL; pPal->palVersion = 0x300; pPal->palNumEntries = nNumEntries; GetPaletteEntries(hpal, 0, nNumEntries, (LPPALETTEENTRY)pPal->palPalEntry); hpal = CreatePalette(pPal); delete [] (BYTE*)pPal; return hpal; } /// /// Copy an area from a bitmap (or the whole bitmap) /// HBITMAP SCCopyBitmap(HBITMAP hbm, HDC hdc/*=NULL*/, LPRECT prect/*=NULL*/) { ASSERT(hbm); BITMAP bm; if (!hbm || !GetObject(hbm, sizeof(bm), &bm)) { #ifdef _DEBUG DWORD dwError = GetLastError(); //SCShowError(); #endif return NULL; } BOOL bTmpDC = (NULL==hdc); if (bTmpDC) hdc = GetDC(NULL); int iCx = prect ? prect->right - prect->left : bm.bmWidth; int iCy = prect ? prect->bottom - prect->top : bm.bmHeight; HBITMAP hNewBm = CreateCompatibleBitmap(hdc, iCx, iCy); if (hNewBm) { HDC hMemDCsrc = CreateCompatibleDC(hdc); HDC hMemDCdst = CreateCompatibleDC(hdc); HBITMAP hOldBMSrc = (HBITMAP)SelectObject(hMemDCsrc, hbm); HBITMAP hOldBMDest = (HBITMAP)SelectObject(hMemDCdst, hNewBm); BitBlt(hMemDCdst, 0, 0, iCx, iCy, hMemDCsrc, prect ? prect->left : 0, prect ? prect->top : 0, SRCCOPY); SelectObject(hMemDCsrc, hOldBMSrc); SelectObject(hMemDCdst, hOldBMDest); DeleteDC(hMemDCsrc); DeleteDC(hMemDCdst); } if (bTmpDC) ReleaseDC(NULL, hdc); return hNewBm; }